﻿using log4net;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Hjt212Parser
{
    /// <summary>
    /// 从212协议解析各种字段
    /// </summary>
    public static class Parser
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(Parser));
        /// <summary>
        /// 获取对应字段（FieldType里定义的）的内容，统一返回string类型
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string GetStringByKey(string key, string content)
        {
            if (string.IsNullOrWhiteSpace(content))
            {
                Log.Warn("The message is null!");
                return null;
            }
            if (string.IsNullOrWhiteSpace(key))
            {
                Log.Warn("The key is null!");
                return null;
            }
            string value = null;

            var matched = true;
            switch (key.ToUpper())
            {
                case "LENGTH":
                    value = Regex.Match(content, "#[0-9]{4}").Value.Replace("#", "");
                    break;
                case "PACKAGE":
                    value = Regex.Match(content, "#[0-9]{4}.*&&[A-Fa-f0-9]{4}").Value;
                    break;
                case "DATASEGMENT":
                    value = Regex.Match(content, "#[0-9]{4}.*&&[A-Fa-f0-9]{4}").Value;

                    value = Regex.Replace(value, "#[0-9]{4}", "");
                    value = Regex.Replace(value, "&&[A-Fa-f0-9]{4}", "");
                    if (value.Length > 0)
                        value = value + "&&";
                    break;
                case "CRC":
                    value = Regex.Match(content, "&&[0-9A-Fa-f]{4}").Value;
                    value = value.Replace("&&", "");
                    break;
                case "MN":
                    //MMNxxxxxxxxxxxxxx
                    //MN=xxxxxxxxxxxxxx
                    value = Regex.Match(content, "MN=[0-9A-Za-z]*[&|,|;]{1}").Value;
                    value = value.Replace("MN=", "").Replace("&", "").Replace(",", "").Replace(";", "");
                    if (string.IsNullOrEmpty(value))
                    {
                        value = Regex.Match(content, "MN[0-9A-Za-z]{14}").Value;
                        value = value.Replace("MN", "");
                    }
                    break;
                case "CP":
                    value = Regex.Match(content, "CP=&&.*&&").Value;
                    value = value.Replace("CP=&&", "").Replace("&&", "");
                    break;
                default:
                    matched = false;
                    break;

            }
            if (!matched)
            {
                value = Regex.Match(content, "#[0-9]{4}").Value;
                if (!string.IsNullOrWhiteSpace(value))
                    content = content.Replace(value, "#");
                value = Regex.Match(content, "[#|&|,|;]{1}" + key + @"=[A-Za-z0-9\.-]+" + "[&|,|;]{1}").Value;
                value = value.Replace("#", "").Replace("&", "").Replace(",", "").Replace(";", "").Replace(key + "=", "");

            }
            if (string.IsNullOrWhiteSpace(value))
            {
                Log.Warn(string.Format("The key '{0}' is missing!", key));
            }
            return value;
        }

        /// <summary>
        /// 获取对应字段（FieldType里定义的）的内容，统一返回int？类型
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static int? GetIntByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                int result = int.Parse(value);
                return result;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
                return null;
            }
        }
        /// <summary>
        /// 获取对应字段（FieldType里定义的）的内容，float？
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static float? GetFloatByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                float result = float.Parse(value);
                return result;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
                return null;
            }
        }
        /// <summary>
        /// 获取对应字段（FieldType里定义的）的内容，统一返回double？类型
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static double? GetDoubleByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                double result = double.Parse(value);
                return result;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
                return null;
            }
        }
        /// <summary>
        /// 获取对应字段（FieldType里定义的）的内容，统一返回bool类型
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static bool? GetBoolByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                bool result = bool.Parse(value);
                return result;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
                return null;
            }
        }

        ///// <summary>
        ///// 获取对应CP中字段的内容，统一返回string类型
        ///// 主要针对污染物因子：譬如B01和01作了处理
        ///// </summary>
        ///// <param name="key"></param>
        ///// <param name="content">可以是CP或包含CP的字符串</param>
        ///// <returns></returns>
        //public static string GetStringByKey(string key, string content)
        //{
        //    var value = Regex.Match(content, "[#|&|,|;]" + key + "=[A-Za-z0-9.-]*" + "[&|,|;]").Value;
        //    return value.Replace("#", "").Replace("&", "").Replace(",", "").Replace(";", "").Replace(key + "=", "");
        //}

        public static string GetStringByKeyCh(string key, string content)
        {
            string value = null;
            try
            {
                value = Regex.Match(content, "[#|&|,|;]{1}" + key + "=.*" + "[&|,|;]{1}").Value;
                if (string.IsNullOrEmpty(value)) return null;
                var ch = value.Split('=')[1].Split(';')[0].Replace("&", "");
                return ch;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
                return null;
            }
        }
        ///// <summary>
        ///// 获取对应CP中字段的内容，统一返回string类型
        ///// 主要针对污染物因子：譬如B01和01作了处理
        ///// </summary>
        ///// <param name="key"></param>
        ///// <param name="content">可以是CP或包含CP的字符串</param>
        ///// <returns></returns>
        //public static string GetChineseStringByKey(string key, string content)
        //{
        //    //\x00-\xff
        //    var value = Regex.Match(content, "[,|;]" + key + "=.{2}").Value;
        //    //if (value.Length < 1)
        //    //{
        //    //    value = Regex.Match(content, key + "=.{4}").Value;
        //    //}
        //    value = Regex.Match(value, "=.{2}").Value;
        //    //if (value.Length < 1)
        //    //{
        //    //    value = Regex.Match(content, key + "=[\xb0-\xf7][\xa0-\xfe][\xb0-\xf7][\xa0-\xfe]").Value;
        //    //}
        //    //value = Regex.Match(value, "=[\xb0-\xf7][\xa0-\xfe][\xb0-\xf7][\xa0-\xfe]").Value;

        //    return value.Replace("=", "");
        //}
        /// <summary>
        ///  获取对应Key的日期数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static DateTime? GetDateTimeByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                var format = "";
                switch (value.Length)
                {
                    case 14:
                        format = "yyyyMMddHHmmss";
                        break;
                    case 17:
                        format = "yyyyMMddHHmmssfff";
                        break;
                }
                if (format.Length > 1)
                {
                    DateTime result = DateTime.ParseExact(value, format, System.Globalization.CultureInfo.CurrentCulture);
                    return result;
                }
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);
            }
            return null;
        }

        /// <summary>
        ///  获取对应Key的decimal数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static decimal? GetDecimalByKey(string key, string content)
        {
            string value = null;
            try
            {
                value = GetStringByKey(key, content);
                if (string.IsNullOrEmpty(value)) return null;
                decimal result = decimal.Parse(value);
                return result;
            }
            catch (Exception ex)
            {
                Log.Error("The key '" + key + "' is " + "'" + value + "':" + ex.Message + "\n" + content);

                return null;
            }
        }

        /// <summary>
        ///  获取污染物因子集合
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static List<string> GetPollutantCodes(string content)
        {
            List<string> codes = new List<string>();
            var cp = GetStringByKey("CP", content);
            var items = Regex.Matches(cp, "[&|,|;]{1}[A-Za-z0-9]+-[A-Za-z0-9]+=");
            foreach (Match item in items)
            {
                var pollutantKey = Regex.Replace(item.Value, "-[A-Za-z]+=", "");
                pollutantKey = Regex.Replace(pollutantKey, "[&|,|;]{1}", "");
                if (pollutantKey.Length > 0 && !codes.Contains(pollutantKey))
                {
                    codes.Add(pollutantKey);
                }
            }
            if (codes.Count < 1)
            {
                Log.Error(string.Format("No factor : {0}", content));
            }
            return codes;
        }

        public static List<string> GetPollutantExprs(string content)
        {
            List<string> codes = new List<string>();
            var cp = "&&" + GetStringByKey("CP", content) + " && ";
            //var cp =  GetStringByKey("Cp, content) ;
            var items = Regex.Matches(cp, "[&|,|;]{1}[A-Za-z0-9]+-[A-Za-z0-9]+=");
            foreach (Match item in items)
            {
                var pollutantKey = Regex.Replace(item.Value, "=", "");
                pollutantKey = Regex.Replace(pollutantKey, "[&|,|;]{1}", "");
                if (pollutantKey.Length > 0 && !codes.Contains(pollutantKey))
                {
                    codes.Add(pollutantKey);
                }
            }
            return codes;
        }
        /// <summary>
        /// 是否顾浩总量or浙江总量心跳包
        /// </summary>
        /// <param name="line">输入串</param>
        /// <returns>真假</returns>
        public static bool IsHeartBeatPackage(string line)
        {

            string value = Regex.Match(line, "MN[0-9]{14}").Value;
            return value.Length == 16;

        }

        public static bool IsHeartBeatPackageZhejiang(string line)
        {


            string st = Regex.Match(line, "ST=28;").Value;
            return st.Length == 6;
        }
        /// <summary>
        /// 长度是否正确，长度正确就认为字符串正确.增加浙江规则判断
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public static bool IsLengthRight(string line)
        {
            var value = GetIntByKey("Length", line);
            if (!value.HasValue) return false;
            string segment = GetStringByKey("DataSegment", line);
            return segment.Length == value;
        }

        public static bool IsLengthRightZhejiang(string line)
        {
            var st = GetStringByKey("ST", line);
            if (!string.IsNullOrEmpty(st) && (!st.Equals("32") || !st.Equals("31"))) return true;
            return false;
        }
        /// <summary>
        /// crc是否正确，不作为判断字符串的依据，crc生成方法较多
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public static bool IsCrcRight(string line)
        {
            string crc = GetStringByKey("Crc", line);
            string segment = GetStringByKey("DataSegment", line);
            return Crc.GenCrc(segment, CrcType.Monitor).ToUpper().Equals(crc) || Crc.GenCrc(segment, CrcType.GuHaoTotal).ToUpper().Equals(crc);
        }
        /// <summary>
        /// 是否为212协议
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static bool IsHjt212Protocol(string content)
        {
            return GetStringByKey("Package", content).Length > 0;
        }
        /// <summary>
        /// 根据字符串的DataTime获取时间，如果没有就根据Qn，如果没有就返回当前时间
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static DateTime GetDateTimeByDataTimeThenQnThenNow(string content)
        {

            var result = GetDateTimeByKey("DataTime", content);
            if (result.HasValue)
            {
                return result.Value;
            }
            result = GetDateTimeByKey("QN", content);
            if (result.HasValue)
            {
                return result.Value;
            }
            return DateTime.Now;
        }
    }
}
